package com.jcfk.eam.service.mould;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.jcfk.common.business.service.BaseService;
import com.jcfk.common.core.utils.BeanUtils;
import com.jcfk.common.security.utils.SecurityUtils;
import com.jcfk.common.web.domain.DataPage;
import com.jcfk.common.web.domain.RetResult;
import com.jcfk.eam.dao.mould.MouldGroupDetailDao;
import com.jcfk.eam.domain.dto.mould.MouldGroupDetailDTO;
import com.jcfk.eam.domain.po.main.EamAssetInfo;
import com.jcfk.eam.domain.po.mould.MouldWorkRecord;
import com.jcfk.eam.domain.po.mould.MouldGroupDetail;
import com.jcfk.eam.domain.po.mould.MouldGroupRecord;
import com.jcfk.eam.domain.query.mould.MouldGroupDetailQuery;
import com.jcfk.eam.enums.AssetKind;
import com.jcfk.eam.service.main.EamAssetInfoService;
import com.jcfk.eam.service.mould.strategy.MouldGroupStrategy;
import com.jcfk.eam.service.mould.strategy.MouldGroupStrategyFactory;
import com.jcfk.eam.util.enums.CodeParseEnu;
import com.jcfk.system.api.utils.DictionaryUtils;
import com.jcfk.system.domain.dto.SysDictionaryItemDTO;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;
import java.util.function.BiFunction;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static com.jcfk.common.core.utils.BeanUtils.convertList;

/**
 * 模具组合记录详情表
 *
 * @author yrl
 * @email
 * @date 2024-11-11
 */
@Service
public class MouldGroupDetailService extends BaseService<MouldGroupDetailDao, MouldGroupDetail> {

    @Resource
    private DictionaryUtils dictionaryUtils;
    @Resource
    private MouldWorkRecordService mouldWorkRecordService;
    @Resource
    private EamAssetInfoService eamAssetInfoService;

    /**
     * ModGroupDetail分页查询
     *
     * @param page  分页设置
     * @param query 查询条件
     * @return 分页查询结果
     */
    public DataPage<MouldGroupDetailDTO> queryByPage(DataPage<MouldGroupDetailDTO> page, MouldGroupDetailQuery query) {
        // 分页查询
        page = this.baseMapper.queryByPage(page, query);
        return page;
    }


    /**
     * 判断ModGroupDetail是已经存在
     *
     * @param dto
     * @return
     */
    public RetResult<String> isValid(MouldGroupDetailDTO dto) {
        QueryWrapper<MouldGroupDetail> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("deleted", 0);

        return RetResult.ok();
    }

    /**
     * 插入模具组合记录详情表
     *
     * @param dto 插入对象
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public void insert(MouldGroupDetailDTO dto) {

        // 保存
        MouldGroupDetail item = new MouldGroupDetail();
        BeanUtils.copyProperties(dto, item);
        this.setDefaultValue(item);

        super.save(item);
    }

    /**
     * 更新模具组合记录详情表
     *
     * @param dto 更新对象
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public void update(MouldGroupDetailDTO dto) {

        // 保存
        MouldGroupDetail item = new MouldGroupDetail();
        BeanUtils.copyProperties(dto, item);

        // 默认数据
        this.setDefaultValue(item);

        super.updateById(item);
    }

    /**
     * 根据批量主键删除模具组合记录详情表(逻辑删除)
     *
     * @param dto
     * @return bool
     */
    @Transactional(rollbackFor = Exception.class)
    public Boolean logicDeleteList(MouldGroupDetailDTO dto) {

        MouldGroupDetail item = new MouldGroupDetail();

        this.setDefaultValue(item);
        item.setDeleted("1");

        QueryWrapper<MouldGroupDetail> queryWrapper = new QueryWrapper<>();
        queryWrapper.in("id", dto.getIds());

        return this.update(item, queryWrapper);
    }

    /**
     * 设置添加默认值
     *
     * @param item 添加对象
     */
    public void setDefaultValue(MouldGroupDetail item) {
        if (StrUtil.isEmpty(item.getCreatedUserId())) {
            item.setCreatedUserId(SecurityUtils.getUserId());
            item.setCreateTime(new Date());
            item.setDeleted("0");
            item.setEnabled("1");
            item.setCreatedUserName(SecurityUtils.getUserName());
        }
        item.setLastUpdatedUserId(SecurityUtils.getUserId());
        item.setLastUpdateTime(new Date());

        item.setLastUpdatedUserName(SecurityUtils.getUserName());

    }

    /**
     * 根据主键获取模具组合记录详情表信息
     *
     * @param id 主键
     * @return StandardCodeDTO
     */
    public MouldGroupDetailDTO get(String id) {
        // 查询数据
        MouldGroupDetail item = this.baseMapper.selectById(id);
        MouldGroupDetailDTO dto = new MouldGroupDetailDTO();
        try {
            BeanUtils.copyProperties(item, dto);
        } catch (RuntimeException e) {
            throw e;
        }

        return dto;
    }

            /**
         * 模具组合记录详情表批量保存
         *
         * @param dtos
         * @return StandardCodeDTO
         */
        @Transactional(rollbackFor = Exception.class)
        public void saveBatch(List<MouldGroupDetailDTO> dtos, MouldGroupRecord mouldGroupRecord) {
            List<MouldGroupDetail> mouldGroupDetails = this.validAndConvert(dtos, mouldGroupRecord.getId());
            QueryWrapper<MouldGroupDetail> queryWrapper = new QueryWrapper<>();
            queryWrapper.lambda().eq(MouldGroupDetail::getGroupRecordId, mouldGroupRecord.getId())
                    .eq(MouldGroupDetail::getDeleted, "0");
            List<MouldGroupDetail> allOld = this.list(queryWrapper);

        Map<String, MouldGroupDetail> oldMap = allOld.stream().collect(Collectors.toMap(MouldGroupDetail::getMouldCode, Function.identity()));
        Map<String, MouldGroupDetail> newMap = mouldGroupDetails.stream().collect(Collectors.toMap(MouldGroupDetail::getMouldCode, Function.identity()));


        // 已存在的和需要组装的所有数据的资产信息
        Map<String, EamAssetInfo> assetInfoMap = eamAssetInfoService.list(Wrappers.<EamAssetInfo>lambdaQuery()
                        .in(EamAssetInfo::getAssetCode,
                                Stream.concat(allOld.stream().map(MouldGroupDetail::getMouldCode),
                                                mouldGroupDetails.stream().map(MouldGroupDetail::getMouldCode))
                                        .collect(Collectors.toList())))
                .stream().collect(Collectors.toMap(EamAssetInfo::getAssetCode, Function.identity()));


            List<MouldWorkRecord> mouldWorkRecordList = new ArrayList<>();
            // 修改已存在列表数据
            List<MouldGroupDetail> updateList = allOld.stream().filter(t -> {
                MouldGroupDetail mouldGroupDetail = newMap.get(t.getMouldCode());
                MouldGroupStrategy strategy = MouldGroupStrategyFactory.getStrategy(t, mouldGroupDetail);
                String process = strategy.process(t, mouldGroupDetail);
                if (StrUtil.isNotEmpty(process)){
                    // 99 表示只修改 不新增操作记录
                    if (!"99".equals(process)){
                        mouldWorkRecordList.add(buildWorkRecord(assetInfoMap, t.getMouldCode(), mouldGroupRecord, process));
                    }
                    return true;
                }
                return false;
            }).collect(Collectors.toList());

            // 判断新纪录列表是否需要新增
            List<MouldGroupDetail> insertList = mouldGroupDetails.stream()
                    .filter(t -> !oldMap.containsKey(t.getMouldCode()))
                    .collect(Collectors.toList());

            if (CollUtil.isNotEmpty(insertList))
                mouldWorkRecordList.addAll(buildWorkRecord(insertList, mouldGroupRecord,"3"));

        this.saveBigBatch(insertList);
        this.updateBigBatch(updateList);
        mouldWorkRecordService.saveBigBatch(mouldWorkRecordList);


    }

    private List<MouldGroupDetail> validAndConvert(List<MouldGroupDetailDTO> dtos, String id) {
        List<String> errorMouldCodes = new ArrayList<>();
        Consumer<MouldGroupDetailDTO> consumer = (item) -> {
            // 如果模具编码不为空  并且正则校验错误 添加到错误集合
            if (StrUtil.isNotEmpty(item.getMouldCode()) && !CodeParseEnu.MOULD_CODE.matcher(item.getMouldCode()))
                errorMouldCodes.add(item.getMouldCode());
        };
        // 判断是否存在错误模具编码
        dtos.forEach(item -> {
            consumer.accept(item);
            if (CollUtil.isNotEmpty(item.getDetails())) item.getDetails().forEach(consumer);
        });
        Assert.isTrue(CollUtil.isEmpty(errorMouldCodes), "模具编号:{},格式不正确", StrUtil.join(",", errorMouldCodes));

        List<MouldGroupDetail> mouldGroupDetails = convertTreeToList(dtos, id);
        long distinctMouldCount = mouldGroupDetails.stream().map(MouldGroupDetail::getMouldCode).distinct().count();
        Assert.isTrue(distinctMouldCount == mouldGroupDetails.size(), "模具编码不能重复");
        return mouldGroupDetails;
    }


    /**
     * 根据条件获取单表信息列表
     *
     * @param query 查询条件
     * @return List<ModGroupDetailDTO>
     */
    public List<MouldGroupDetailDTO> getList(MouldGroupDetailQuery query) {
        // 查询条件
        QueryWrapper<MouldGroupDetail> qw = new QueryWrapper<>();
        qw.lambda().eq(!StrUtil.isEmpty(query.getGroupRecordId()), MouldGroupDetail::getGroupRecordId, query.getGroupRecordId());
        // 查询数据
        List<MouldGroupDetail> list = super.list(qw);

        return convertList(list, MouldGroupDetailDTO.class);
    }

    /**
     * 根据主键获取模具组合记录详情表信息
     *
     * @param id 主键
     * @return StandardCodeDTO
     */
    public void deleteItem(String id) {
        MouldGroupDetail item = getById(id);
        this.setDefaultValue(item);
        item.setDeleted("1");

        this.updateById(item);
    }


    private List<MouldGroupDetail> convertTreeToList(List<MouldGroupDetailDTO> dtos, String groupRecordId) {
        BiFunction<String, String, String> function = (code, label) -> Optional.ofNullable(dictionaryUtils.getDictionaryItems(code)
                        .stream()
                        .filter(d -> d.getItemLabel().equals(label))
                        .findFirst()
                        .orElse(new SysDictionaryItemDTO())
                        .getItemValue())
                .orElse("1");
        String mouldStatus = function.apply("mouldStatus", "组合");
        String groupStatus = function.apply("groupStatus", "空闲");
        return dtos.stream()
                .map(detail -> {
                    List<MouldGroupDetail> results = new ArrayList<>();
                    MouldGroupDetail item = new MouldGroupDetail();
                    BeanUtils.copyProperties(detail, item);
                    this.setDefaultValue(item);
                    item.setGroupRecordId(groupRecordId);
                    item.setGroupStatus(groupStatus);
                    item.setMouldStatus(mouldStatus);
                    if (CollUtil.isNotEmpty(detail.getDetails())) {
                        results.addAll(convertTreeToList(detail.getDetails(), groupRecordId));
                    }
                    Assert.notEmpty(detail.getMouldCode(), "{}:模具编码不能为空", detail.getDisplayCode());
                    results.add(item);
                    return results;
                })
                .flatMap(Collection::stream)
                .filter(item -> StrUtil.isNotEmpty(item.getMouldCode()))
                .collect(Collectors.toList());
    }

    @Transactional
    public void scatter(MouldGroupRecord groupRecord) {
        BiFunction<String, String, String> function = (code, label) -> Optional.ofNullable(dictionaryUtils.getDictionaryItems(code)
                        .stream()
                        .filter(d -> d.getItemLabel().equals(label))
                        .findFirst()
                        .orElse(new SysDictionaryItemDTO())
                        .getItemValue())
                .orElse("2");
        QueryWrapper<MouldGroupDetail> queryWrapper = new QueryWrapper<>();
        queryWrapper.in("group_record_id", groupRecord.getId());
        queryWrapper.eq("deleted", "0");
        // 查询所有组合的模具
        queryWrapper.eq("group_status", "1");
        List<MouldGroupDetail> list = this.list(queryWrapper);
        String mouldStatus = function.apply("mouldStatus", "未组");
        list.forEach(item -> {
            item.setLastUpdatedUserId(SecurityUtils.getUserId());
            item.setLastUpdateTime(new Date());
            item.setLastUpdatedUserName(SecurityUtils.getUserName());
            item.setGroupStatus(mouldStatus);
        });
        this.updateBigBatch(list);
        List<MouldWorkRecord> mouldWorkRecordList = buildWorkRecord(list, groupRecord, "4");
        mouldWorkRecordService.saveBigBatch(mouldWorkRecordList);
    }

    private List<MouldWorkRecord> buildWorkRecord(List<MouldGroupDetail> mouldGroupDetailList, MouldGroupRecord mouldGroupRecord, String workKind) {
        // 所有组合的模具的资产信息
        Map<String, EamAssetInfo> assetInfoMap = eamAssetInfoService.list(Wrappers.<EamAssetInfo>lambdaQuery()
                        .in(EamAssetInfo::getAssetCode, mouldGroupDetailList.stream().map(MouldGroupDetail::getMouldCode).collect(Collectors.toList())))
                .stream()
                .collect(Collectors.toMap(EamAssetInfo::getAssetCode, Function.identity()));
        return mouldGroupDetailList.stream()
                .map(detail -> buildWorkRecord(assetInfoMap,detail.getMouldCode(), mouldGroupRecord,workKind))
                .collect(Collectors.toList());
    }
    private MouldWorkRecord buildWorkRecord(Map<String, EamAssetInfo> assetInfoMap, String mouldCode, MouldGroupRecord mouldGroupRecord, String workKind) {
        EamAssetInfo eamAssetInfo = Optional.ofNullable(assetInfoMap.get(mouldCode))
                .orElseThrow(() -> new IllegalArgumentException("未找到工装编码为【" + mouldCode + "】的工装信息"));
        MouldWorkRecord eamModWorkRecord = new MouldWorkRecord();
        mouldWorkRecordService.setDefaultValue(eamModWorkRecord);
        eamModWorkRecord.setGroupCode(mouldGroupRecord.getMouldCode());
        eamModWorkRecord.setMouldCode(eamAssetInfo.getAssetCode());
        eamModWorkRecord.setWorkTime(new Date());
        eamModWorkRecord.setWorkKind(workKind);
//        eamModWorkRecord.setProductCode(eamAssetInfo.getProductCode());
//        eamModWorkRecord.setEquipCode(eamAssetInfo.getEquipCode());
//        eamModWorkRecord.setProjectCode(eamAssetInfo.getProjectCode());
//        eamModWorkRecord.setProcessCode(eamAssetInfo.getProcessCode());
//        eamModWorkRecord.setMaterialCode(eamAssetInfo.getMaterialCode());
//        eamModWorkRecord.setMaterialId(eamAssetInfo.getMaterialId());
//        eamModWorkRecord.setMaterialName(eamAssetInfo.getMaterialName());
        eamModWorkRecord.setMaterialGroup(eamAssetInfo.getAssetTypeCode());
        eamModWorkRecord.setAssetKind(AssetKind.MOULD.getValue());
        eamModWorkRecord.setEnabled("1");
        return eamModWorkRecord;
    }
}

